using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Peak.Can.Basic;
using System.IO.Ports;
using TPCANHandle = System.Byte;


namespace WinCANTool
{


    public partial class FlashWindow1319 : Form
    {
        public delegate int showRxTraceDelegate(ref TPCANMsg MessageIn, bool TimeStampOn);

        public event showRxTraceDelegate CANMsgRxEvent;
        

        private void FactoryUserInit(bool FactoryUser)
        {
            if (FactoryUser)
            {
                //dataGridView2.Visible = true;
                //pictureBox1.Visible = true;
                //TxClear.Visible = true;
                NetStatus.Visible = true;
                
            }
            else
            {
                //dataGridView2.Visible = false;
                //pictureBox1.Visible = false;
                //TxClear.Visible = false;
                NetStatus.Visible = false;

            }

            this.CANMsgRxEvent += new showRxTraceDelegate(ShowRxString);
        
        }



        public void StartThreads()
        {
            SDOVarInitMDI();
            //m_thread = new Thread(new ThreadStart(CANRcvThreadProcNew));
            m_thread = new Thread(new ThreadStart(CANRcvThreadProc));
            //m_thread.Priority = ThreadPriority.Highest;
            mdi_thread = new Thread(new ThreadStart(CANRxBufferThread));
            m_fThreadTerminated = false;
            mdi_fThreadTerminated = false;

        }

        public void StartLindeCanThreads()
        {
            SDOVarInitMDI();
            //m_thread = new Thread(new ThreadStart(CANRcvThreadProcNew));
            m_thread = new Thread(new ThreadStart(LindeCANRcvThreadProc));
            //m_thread.Priority = ThreadPriority.Highest;
            mdi_thread = new Thread(new ThreadStart(CANRxBufferThread));
            m_fThreadTerminated = false;
            mdi_fThreadTerminated = false;

        }       



        public void StartFlashThread()
        {
            f_thread = new Thread(new ThreadStart(GetBlockCount));
            //f_thread.Priority = ThreadPriority.Highest;
            f_fThreadTerminated = false;
            f_thread.Start();
        }

        public void StartKWPThread()
        {
            f_kwpthread = new Thread(new ThreadStart(ProcessKWP));
            f_fKwpThreadTerminated = false;
            f_kwpthread.Start();
        }
        


        public void StartSegmentThread()
        {
            f_thread = new Thread(new ThreadStart(SegmentTransfer));
            //m_thread.Priority = ThreadPriority.Highest;
            f_fThreadTerminated = false;
            f_thread.Start();

        }



        public void StartCANValueThread()
        {
            f_thread = new Thread(new ThreadStart(CANValueTransfer));
            //m_thread.Priority = ThreadPriority.Highest;
            f_fThreadTerminated = false;
            f_thread.Start();

        }


        public void StartProfileThread()
        {
            prof_thread = new Thread(new ThreadStart(DeviseProfileThread));
            //m_thread.Priority = ThreadPriority.Highest;
            prof_fThreadTerminated = false;
            prof_thread.Start();

        }

        
        public void AbortFlashThread()
        {
            if(!f_fThreadTerminated)
                f_thread.Abort();
            f_fThreadTerminated = true;
        }


        public void AbortKWPThread()
        {
            if(!f_fKwpThreadTerminated)
                f_kwpthread.Abort();
            f_fKwpThreadTerminated = true;
        }

        public void AbortProfThread()
        {
            if (!prof_fThreadTerminated)
                prof_thread.Abort();
            prof_fThreadTerminated = true;
        }

        

        //public void CANRcvThreadProcNew()
        //{
        //    uint ret;
        //    byte RcvNet;
        //    m_hClient = ParentForm.GetClientHandle();

        //    MsgIn NewRxMsg = new MsgIn();

        //    CanApi2.SetClientParam(m_hClient, CanApi2.PARAM_ONRCV_EVENT_HANDLE, (uint)m_RcvEvent.Handle);
        //    while (!m_fThreadTerminated)
        //    {
        //        m_RcvEvent.WaitOne();
        //        // Read messages until queue is empty

        //        do
        //        {
        //            if ((!HaltThreadRead) && !LockDisplay)
        //            {
        //                ret = CanApi2.Read(m_hClient, out NewRxMsg.msgInRx, out RcvNet, out NewRxMsg.RcvTimeRx);

        //                if (ret == CanApi2.ERR_OK)
        //                {
        //                    if (FlashOpOn)
        //                        AddRXMessage(NewRxMsg.msgInRx);

        //                    if (ParentForm.NodeDisplay.SearchActive)
        //                    {
        //                        ParentForm.NodeDisplay.BaudRateFound = true;
        //                    }
        //                    else
        //                    {
        //                        // Evaluate message
        //                        if (ParentForm.InhibitWindow.Created)
        //                        {
        //                            ParentForm.InhibitWindow.AddData(NewRxMsg.msgInRx);
        //                        }

        //                        //AddMessageRx(NewRxMsg.msgInRx, NewRxMsg.RcvTimeRx);
        //                        if(!OverFlowFault)
        //                            AddRXMessageMDI(NewRxMsg.msgInRx, NewRxMsg.RcvTimeRx);
        //                    }
        //                }
        //                else if (ret == CanApi2.ERR_QRCVEMPTY)
        //                {
        //                    LockDisplay = false;
        //                }

        //                else if (ret != CanApi2.ERR_QRCVEMPTY)  // error
        //                {
        //                }
        //            }
        //            else
        //                ret = 0;
        //        }
        //        while ((ret & CanApi2.ERR_QRCVEMPTY) != 0);
        //    }

        //    // Cleanup
        //    CanApi2.SetClientParam(m_hClient, CanApi2.PARAM_ONRCV_EVENT_HANDLE, 0);
        //}


        public void CANRcvThreadProc()
        {
            //uint ret;
            TPCANStatus stsResult = TPCANStatus.PCAN_ERROR_OK;
            TPCANTimestamp CANTimeStamp;
            //int MessageCount = 0;
            m_hClient = ParentForm.GetClientHandle();
            m_hHw = ParentForm.GetHwHandle();
            UInt32 iBuffer = Convert.ToUInt32(m_RcvEvent.SafeWaitHandle.DangerousGetHandle().ToInt32());

            //MsgIn NewRxMsg = new MsgIn();


            stsResult = PCANBasic.SetValue(m_hClient, TPCANParameter.PCAN_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));

            if(stsResult != TPCANStatus.PCAN_ERROR_OK)
            {
                MessageBox.Show("Receive event Error!");
                return;
            }
            //CanApi2.SetClientParam(m_hClient, CanApi2.PARAM_ONRCV_EVENT_HANDLE, (uint)m_RcvEvent.Handle);
            while (!m_fThreadTerminated)
            {
                m_RcvEvent.WaitOne(50); 
                do
                {
                    stsResult = PCANBasic.Read(m_hClient, out ReceiveBufferHW, out CANTimeStamp);
                    if (stsResult == TPCANStatus.PCAN_ERROR_OK)
                    {
                        if (FlashOpOn)
                        {
                            if(ReceiveBufferHW.ID != 0)
                               AddRXMessage(ReceiveBufferHW);
                        }
                    }
                    else if (stsResult == TPCANStatus.PCAN_ERROR_QRCVEMPTY)  // error
                    {
                       //Thread.Sleep(2);    
                    }
                    else
                    {
                        PCANBasic.Reset(m_hClient);
                    }
                }
                while(stsResult != TPCANStatus.PCAN_ERROR_QRCVEMPTY);
            }
        }

        public void LindeCANRcvThreadProc()
        {
            m_hSerialPort = ParentForm.GetSerialHandle();
            while (!m_fThreadTerminated)
            {
                Thread.Sleep(50);   

                m_hSerialPort.ReadTimeout = 1;

                if (m_hSerialPort.BytesToRead > 0)
                {
                    Thread.Sleep(2); // wait complete
                    byte data = Convert.ToByte(m_hSerialPort.ReadByte());

                    if (data == 0x02) // frame start
                    {
                        int bytesRead = m_hSerialPort.BytesToRead;
                        byte[] bytesData = new byte[bytesRead];
                        byte[] frameData = new byte[bytesRead];
                        byte[] bytesCleanData = new byte[bytesRead];
                        byte cks = 0;
                        int frame_start = 0;
                        int frame_len = 0;
                       
                        
                        m_hSerialPort.ReadTimeout = 10;
                        

                        for (int i = 0; i < bytesRead; i++)
                        {
                            bytesData[i] = Convert.ToByte(m_hSerialPort.ReadByte());
                        }
                        

                        for (int i = 0; i < bytesRead-2; i++)
                        {
                            if(bytesData[i] == 0x02)
                            {
                                if(bytesData[i+1] == 0x02)
                                {
                                    i++;
                                }
                                else
                                {
                                    frame_start = i+1;
                                }
                            }
                        }

                        for (int i = frame_start; i < bytesRead; i++)
                        {
                            frameData[frame_len++] = bytesData[i];
                            cks ^= bytesData[i];
                        }                        
                        
                        if (cks == 0)
                        {
                            int j = 0;
                            for (int i = 0; i < frame_len - 1; i++)
                            {
                                bytesCleanData[j++] = frameData[i];
                                if (frameData[i] == 0x02)
                                {
                                    i++;  // skip this one
                                }
                            }

                            byte[] id_byte = new byte[2];
                            id_byte[0] = bytesCleanData[0];
                            id_byte[1] = bytesCleanData[1];

                            ReceiveBufferHW.ID = BitConverter.ToUInt16(id_byte, 0);

                            ReceiveBufferHW.LEN = 8; // fixed

                            ReceiveBufferHW.DATA = new byte[8];

                            
                            int index = 0;

                            for( int k = 2; k < j; k++)
                            {
                                ReceiveBufferHW.DATA[index++] = bytesCleanData[k];
                            }

                            if(ReceiveBufferHW.ID != 0)
                            {
                                AddRXMessage(ReceiveBufferHW);
                            }
                            
                        }
                    }
                }

                
            }
        }
        

        private void AddRXMessageMDI(TPCANMsg MessageIn, TPCANTimestamp TimeStampIn)
        {
            if (SDOMsgInMDI[NextIndex].DisplayDone == true)
            {
                SDOMsgInMDI[NextIndex].msgInRx.ID = MessageIn.ID;
                SDOMsgInMDI[NextIndex].msgInRx.LEN = MessageIn.LEN;
                SDOMsgInMDI[NextIndex].msgInRx.MSGTYPE = MessageIn.MSGTYPE;
                SDOMsgInMDI[NextIndex].RcvTimeRx = TimeStampIn;

                for (int i = 0; i < 8; i++)
                {
                    SDOMsgInMDI[NextIndex].msgInRx.DATA[i] = MessageIn.DATA[i];
                }
                SDOMsgInMDI[NextIndex].DisplayDone = false;
                EndIndex = NextIndex;
                if (NextIndex < (BUFFER_SIZE - 1))
                    NextIndex++;
                else
                    NextIndex = 0;
            }
            else
            {
                if (!OverFlowFault)
                    MessageBox.Show("Receive Buffer OverFlow");
                OverFlowFault = true;
            }
            

        }



        private void CANRxBufferThread()
        {

            MsgIn NewRxMsg = new MsgIn();
            NewRxMsg.msgInRx.DATA = new byte[8];
            //int msgCount;
           // int msgIndex, Index;

            while (!mdi_fThreadTerminated)
            {
                // Read messages until queue is empty

                do
                {
                    if (!HaltThreadRead)
                    {                        
                        //if(!LockDisplay)
                            //AddMessageRx();
                            
                        if(DelayON)
                            Thread.Sleep(2);
                    }
                    else
                       Thread.Sleep(2);
                }
                while (true);

            }
        }




        public void SDOVarInitMDI()
        {

            for (int i = 0; i < BUFFER_SIZE; i++)
            {
                SDOMsgInMDI[i].msgInRx.DATA = new byte[8];
            }
            SDOVarClearMDI();
        }


        private void SDOVarClearMDI()
        {
            //CurrentIndexMDI = 0;
            TxDelayMilli = 0;

            for (int i = 0; i < BUFFER_SIZE; i++)
            {
                SDOMsgInMDI[i].DisplayDone = true;
                SDOMsgInMDI[i].msgInRx.ID = 0;
                SDOMsgInMDI[i].msgInRx.LEN = 0;
                SDOMsgInMDI[i].msgInRx.MSGTYPE = 0;
                SDOMsgInMDI[i].RcvTimeRx.micros = 0;
                SDOMsgInMDI[i].RcvTimeRx.millis = 0;
                SDOMsgInMDI[i].RcvTimeRx.millis_overflow = 0;
                for (int j = 0; j < 8; j++)
                    SDOMsgInMDI[i].msgInRx.DATA[j] = 0;
            }
        }




        public void StopThread()
        {
            // End thread

            m_RcvEvent.Set();
            //m_thread.Join();
            if (!m_fThreadTerminated)
                m_thread.Abort();
            if (!mdi_fThreadTerminated)
                mdi_thread.Abort();
            if (!f_fThreadTerminated)
                f_thread.Abort();
            if (!prof_fThreadTerminated)
                prof_thread.Abort();
            if (!tx_ThreadTerminated)
            {
                KillTxCycle();
                //Cycle_tx_thread.Abort();
            }
            if (!f_fKwpThreadTerminated)
                f_kwpthread.Abort();
            
            tx_ThreadTerminated = true;
            m_fThreadTerminated = true;
            mdi_fThreadTerminated = true;
            f_fThreadTerminated = true;
            f_fKwpThreadTerminated = true;
            //if (CycleThreadOn)
            //    tx_thread.Abort();
            //CycleThreadOn = false;

        }



        public Foundmsg FindMessage(NewMessage msg, List<NewMessage> MessageList, bool RxMessage)
        {
            int index = 0;
            byte[] Data1 = new byte[8];
            byte[] Data2 = new byte[8];

            Foundmsg MessageFound = new Foundmsg();

            MessageFound.gridviewIndex = -1;
            msg.GetData(ref Data1);
            byte DLC = msg.GetDLC();
            int sendrate = msg.GetSendRate();

            foreach (NewMessage Messg in MessageList)
            {
                index++;
                Messg.GetData(ref Data2);
                int rate = Messg.GetSendRate();

                if ((msg.GetIdentifier() == Messg.GetIdentifier()) &&
                  (msg.GetDLC() == Messg.GetDLC()) &&
                  (DataIsEqual(Data1, Data2, DLC, RxMessage)) &&
                  (sendrate == rate))
                {
                    MessageFound.count = Messg.IncreaseCount();
                    MessageFound.gridviewIndex = index;
                    MessageFound.DeltaTime = Messg.GetMessageDelta(msg);
                    MessageFound.Displayed = Messg.GetMessageDisplayed();
                    Messg.SaveMessageDelta(msg.GetTimeStamp().millis);
                    break;
                }
                else
                    MessageFound.Displayed = msg.GetMessageDisplayed();
            }
            if (MessageList.Count == 0)
                MessageFound.Displayed = msg.GetMessageDisplayed();

            return MessageFound;
        }


        public bool DataIsEqual(byte[] Data1, byte[] Data2, byte dlc, bool Rxmsg)
        {
            bool DataEqual = true;

            //for (int i = 0; i < dlc; i++)
            //{
            //    if (Rxmsg)
            //    {
            //        if ((Data1[i] != Data2[i]) && CanDisplayOptions.DataChange[i])
            //            DataEqual = false;
            //    }
            //    else
            //    {
            //        if (Data1[i] != Data2[i])
            //            DataEqual = false;
            //    }
            //}
            return DataEqual;
        }



        /********************************************************************
         * Name: CreateSymbolString
         * Purpose: 
         * Input: NewMessage
         * Output: new incremented message count if the identifer was found
         * or -1 if it was not found in the symbols.
         *
         * Remaining change: 
         ********************************************************************/

        private int CreateSymbolString(ref NewMessage Msg, ref CreateSymbolString NewString, bool TimeStampOn)
        {
            string TempStr = NewString.CreateSymbolStringFromMsg(MsgSymbols.MySymbols,
                Msg, CanDisplayOptions, TimeStampOn);

            if (TempStr != null)   /* A null values means that identifier was not in symbols */
            {
                Msg.SaveDisplayString(TempStr);
                return Msg.IncreaseCount();
            }
            else return -1;

        }


        private int CreateDisplayString(ref NewMessage Msg, bool TimeStampOn)
        {
            string RawDisplayString = NewRawString.CreateRawString(ref Msg, TimeStampOn, false);

            /******   Save Changes  ********************************/

            Msg.SaveDisplayString(RawDisplayString);
            can_tx_textBox.Text = RawDisplayString;
            return Msg.IncreaseCount();

        }


        

        private int ShowRxString(ref TPCANMsg MessageIn, bool TimeStampOn)
        {
            if (this.can_tx_textBox.InvokeRequired)
            {
                showRxTraceDelegate d = new showRxTraceDelegate(ShowRxString);
                this.BeginInvoke(d, new object[] { MessageIn, true  });
            }
            else
            {
                if( data_download == 0)
                {
                    int DLC = MessageIn.LEN;
                    string tempdisplay = "0x"+MessageIn.ID.ToString("X") + "    "+DLC.ToString()+ "    ";
                   
                    string tempdata = "";       
                    for (int i = 0; i < DLC; i++)
                    {
                        tempdata = MessageIn.DATA[i].ToString("X");
                        tempdata = tempdata.PadLeft(2, '0');
                        tempdisplay += tempdata + " ";
                    }
                    can_tx_textBox.AppendText(tempdisplay);
                    can_tx_textBox.AppendText("\r\n");
                }
                else if(data_download == 1)
                {
                    can_tx_textBox.AppendText("downloading...");
                    can_tx_textBox.AppendText("\r\n");
                    data_download = 2;
                }
            }
            return 1;
        }


        private void SendFlashMessage(NewMessage MessageOut)
        {
            SDOVarClear();
            if(ParentForm.GetHardware() == 0)
            {
                SendCanMessage(ref MessageOut);
            }
            else
            {
                SendLindeCanMessage(ref MessageOut);
            }
        }


 
        /*  CanApi.TCANMsg -> USB  */

        private void SendCanMessage(ref NewMessage MessageToSend)
        {
            TPCANStatus stsResult;
            TPCANMsg CANMsgToSend = new TPCANMsg();
            CANMsgToSend = MessageToSend.GetCANMsg();
            m_hClient = ParentForm.GetClientHandle();
            m_hNet = ParentForm.GetNetHandle();
            m_hHw = ParentForm.GetHwHandle();
            TPCANTimestamp tstamp = new TPCANTimestamp();

            MessageToSend.SaveTimeStamp(tstamp);

            stsResult = PCANBasic.Write(m_hClient, ref CANMsgToSend);

            if((stsResult == 0) && (data_download == 0))
            {
                if(this.CANMsgRxEvent != null)
                {
                    CANMsgRxEvent(ref CANMsgToSend, true);  
                }
            }
        }

        private void SendLindeCanMessage(ref NewMessage MessageToSend)
        {
            //TPCANStatus stsResult;
            TPCANMsg CANMsgToSend = new TPCANMsg();
            CANMsgToSend = MessageToSend.GetCANMsg();
            SerialPort h_Port = ParentForm.GetSerialHandle();
            m_hNet = ParentForm.GetNetHandle();
            m_hHw = ParentForm.GetHwHandle();
            TPCANTimestamp tstamp = new TPCANTimestamp();
            byte[] id_byte = new byte[2];

            MessageToSend.SaveTimeStamp(tstamp);

            byte[] bytesSend = new byte[40];             // may not exceed this length, max length 1+4+16+1
            byte cks = 0;
            byte index = 0;
            byte data;

            bytesSend[index++] = 0x02;  // start a frame;

            id_byte = BitConverter.GetBytes(CANMsgToSend.ID);           
            
            data = id_byte[0];  // low byte id
            bytesSend[index++] = data;
            cks ^= data;
            if(data == 0x02)                 
            {
                bytesSend[index++] = 0x02;
                cks ^= data;
            }

            data = id_byte[1];  // high byte id
            bytesSend[index++] = data;
            cks ^= data;
            if(data == 0x02)                 
            {
                bytesSend[index++] = 0x02;
                cks ^= data;
            }

            for(uint i = 0; i < CANMsgToSend.LEN; i++)
            {
                data = CANMsgToSend.DATA[i];
                bytesSend[index++] = data;
                cks ^= data;
                if(data == 0x02)
                {
                    bytesSend[index++] = 0x02;
                    cks ^= data;
                }
            }
            bytesSend[index++] = cks;
            
            h_Port.Write(bytesSend, 0, bytesSend.Length);

            if(data_download == 0)
            {
                if(this.CANMsgRxEvent != null)
                {
                    CANMsgRxEvent(ref CANMsgToSend, true);  
                }
            }
        }


        

        private void CycleMessage(int Index)
        {
            //NewMessage mssg = new NewMessage();
            //Netparms Net = new Netparms();

            //Net.ClientHndl = ParentForm.GetClientHandle();
            //Net.NetHndl = ParentForm.GetNetHandle();
            //Net.HwHndl = ParentForm.GetHwHandle();
            //Net.BaudRateValues = ParentForm.GetBaudValues();
            //Net.BaudRateStrings = ParentForm.GetBaudStrings();

            //GC.Collect();
            //SelectedIndex = dataGridView2.SelectedRows[0].Index;
            //mssg = MessageInList[SelectedIndex];
            //CanApi2.GetSystemTime(out tstamp);
            //Net.Index = Index;

            //tx_ThreadTerminated = false;
            //TxCycleClass = new CycleTxThread(mssg, tstamp, Net, ref CycleBox);
            //TxCycleClass.TxReady += new NewMessageHandler(AddTxMessageEvent1);
            //Cycle_tx_thread = new Thread(new ThreadStart(TxCycleClass.TxThread));
            ////CanApi2.SetClientParam(m_hClient, CanApi2.PARAM_SELF_RECEIVE, 1);

            //Cycle_tx_thread.Start();
            //CurrMsg.gridviewIndex = SelectedIndex + 1;
        }

        private void KillTxCycle()
        {
            //for (int i = 0; i < 10; i++)
            //    CycleBox[i] = false;
        }

        /*public class CycleTxThread
        {
            public int CycleSendRate;
            NewMessage ThreadMess;
            CanApi2.TCANTimestamp tstampTx = new CanApi2.TCANTimestamp();
            Netparms Net;
            bool[] checkbox;
            int threadIndex;
            //int Delay;

            public event NewMessageHandler TxReady;


            public CycleTxThread(NewMessage Msg, CanApi2.TCANTimestamp tstamp, Netparms NetP, ref bool[] Cycle)
            {
                ThreadMess = new NewMessage(Msg);
                tstampTx = tstamp;
                CycleSendRate = Msg.GetSendRate();
                Net = NetP;
                threadIndex = Net.Index;
                checkbox = Cycle;

            }



            public void TxThread()
            {
                TPCANMsg CanMsg = ThreadMess.GetCANMsg();
                uint ret;
                int cycle = 0;
                TPCANStatus stsResult;
                //m_hClient = ParentForm.GetClientHandle();

                while (true)
                {
                    if (checkbox[threadIndex] == false)
                        break;

                    stsResult = PCANBasic.Write(m_hClient, ref CanMsg);
                    
                    CanApi2.GetSystemTime(out tstampTx);
                    
                    NewEventArgs TxEventArgs = new NewEventArgs();
                    ThreadMess.SaveTimeStamp(tstampTx);
                    TxEventArgs.EventMessage = ThreadMess;
                    DisplayCycleTx(TxEventArgs);
                    if (CycleSendRate >= 5)
                        cycle = CycleSendRate - 5;
                    Thread.Sleep(cycle);
                }
                //CanApi2.SetClientParam(Net.ClientHndl, CanApi2.PARAM_SELF_RECEIVE, 0);
            }






            protected virtual void DisplayCycleTx(NewEventArgs e)
            {
                if (TxReady != null)
                    TxReady(this, e);
            }

        }*/





    }

        public class CycleThread
        {
            public int CycleSendRate;
            public int SendCount;
            NewMessage ThreadMess;
            TPCANTimestamp tstampTx = new TPCANTimestamp();
            Netparms Net;
            public event NewMessageHandler TxReady;
            public event EventHandler StepDone;


            public CycleThread(NewMessage Msg, Netparms NetP, int Count)
            {
                ThreadMess = new NewMessage(Msg);
                CycleSendRate = Msg.GetSendRate();
                Net = NetP;
                SendCount = Count;
            }


            public void TxThread()
            {
                uint timestamp;
                TPCANMsg CanMsg = ThreadMess.GetCANMsg();
                //CanApi2.GetSystemTime(out tstampTx);
                timestamp = tstampTx.millis;

                while (ThreadMess.GetCount() < SendCount)
                {
                   // CanApi2.GetSystemTime(out tstampTx);

                    while (tstampTx.millis < (timestamp + ((uint)CycleSendRate - 0)))
                    {
                        //CanApi2.GetSystemTime(out tstampTx);
                    }

                    timestamp = tstampTx.millis;


                    TPCANStatus stsResult = PCANBasic.Write(Net.ClientHndl, ref CanMsg);

                    ThreadMess.IncreaseCount();

                    NewEventArgs TxEventArgs = new NewEventArgs();
                    ThreadMess.SaveTimeStamp(tstampTx);
                    TxEventArgs.EventMessage = ThreadMess;
                    DisplayCycleTx(TxEventArgs);

                    Thread.Sleep(CycleSendRate - 4);
                }
                EventArgs Args = new EventArgs();
                CurrentStepDone(Args);

            }


            protected virtual void DisplayCycleTx(NewEventArgs e)
            {

                if (TxReady != null)
                    TxReady(this, e);
            }

            protected virtual void CurrentStepDone(EventArgs e)
            {
                if (StepDone != null)
                    StepDone(this, e);
            }
        }


}
